
'''	
	This file is part of Roseena.
	
	Copyright (C) 2008	Mohamed Hazem <mohamed.hazem@student.guc.edu.eg>
	Copyright (C) 2008	Mostafa Hany <mostafa.hany@student.guc.edu.eg>

	
	Roseena is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Roseena is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Roseena.	If not, see <http://www.gnu.org/licenses/>.
'''

# TODO: errors.
# TODO: destroy the thread.
# TODO: destroy serverSocket when done.
# TODO: clean the cache.

from PyQt4.QtCore import QObject, QThread, QDataStream,QString, QFile, QIODevice, QDir, QByteArray, QDir, SIGNAL
from PyQt4.QtNetwork import QTcpSocket, QAbstractSocket, QHostAddress

HOST = QHostAddress(QHostAddress.LocalHost)
PORT = 8001
SIZEOF_UINT16 = 2

class proxySocketThread(QThread):
	'''
	socketThread class responsible for threading sockets on simultaneous incoming requests.
	'''
	def __init__(self, socketId, parent):
		'''
		Constructor
		'''
		QThread.__init__(self, parent)
		self.socketId = socketId
		self.nextBlockSize = 0

		self.fileSize = -1
		self.received = 0
		self.file = None

	def run(self):
		print "run for your life"
		self.socket = QTcpSocket()

		if not self.socket.setSocketDescriptor(self.socketId):
			self.emit(SIGNAL("error(int)"), socket.error())
			return

		self.socket.connect(self.socket, SIGNAL("readyRead()"), self.readRequest)

		self.exec_()

	def readRequest(self):
		if self.socket.canReadLine():
			request = self.socket.readLine()
			parts = request.split(' ')

			if len(parts) == 3 and parts[0] == 'GET' and parts[2] == 'HTTP/1.0\n':
				filename = parts[1]
				self.process(filename)
			else:
				self.socket.write("Bad Request\n")

	def process(self, fileName):
		# We have 2 possibilities here:
		# 1) We have the file so we will send it. We are happy.
		# 2) We don't have the file so we will try to get it from the main server.

		
		self.file = QFile("files/%s" % fileName)
#		if file.open(QIODevice.ReadOnly) == True:
		if QFile.exists("files/%s" % fileName) == True:
			file = QFile("files/%s" % fileName)
			file.open(QIODevice.ReadOnly)
			self.sendFile(file)
			file.close()
		else:
			# We failed, it can be because of the file not being there or because of
			# a permissions problem. I don't care and will get it from the server.
			# Ideally, we should get the original request and send it.
			# Too bad we don't have access to it but it's not a big deal anyway ;-)
#			self.file = QFile("files/%s" % fileName)
#			if self.file.open(QIODevice.WriteOnly) == False:
#				print "file open false"
#				self.file = None

			self.requestFile(fileName)

	def sendFile(self, file):
		contents = file.readAll()
		self.socket.write("HIT HTTP/1.0 200 Document follows\n")
		self.socket.write("Content-Length: %i\n" % file.size())
		self.socket.write(contents)
		self.socket.flush()

	def requestFile(self, fileName):
		request = "GET %s HTTP/1.0\n" % fileName
		if self.connectToServer() != True:
			return

		self.serverSocket.write(request)

	def connectToServer(self):
		self.serverSocket = QTcpSocket()
		self.serverSocket.connect(self.serverSocket, SIGNAL("readyRead()"), self.doServerRead)
		self.serverSocket.connectToHost(HOST, PORT)
		return self.serverSocket.waitForConnected(-1)

	def saveAndSend(self):
		self.file.open(QIODevice.Append)
		
		data = self.serverSocket.readAll()
		self.received = self.received + len(data)
		# TODO: error checking.
		self.file.write(data)
		self.socket.write(data)

		if self.fileSize == self.received:
			self.serverSocket.close()
			self.file.close()
			self.file = None
			self.fileSize = -1
			self.received = 0

	def doServerRead(self):
		print "doServerRead"
		# Do we know the size ?
		if self.fileSize != -1:
			self.saveAndSend()
		else:
			while self.serverSocket.canReadLine() == True:
				if self.fileSize == -1:
					resp = self.serverSocket.readLine()
					self.processLine(resp)
				else:
					return self.doServerRead()

	def processLine(self, line):
		if line.startsWith("HTTP"):
			# TODO: Should we delay sending this ?
			self.socket.write("MISS " + line)

		elif line.startsWith("Content-Length"):
			parts = line.split(" ")
			if len(parts) != 2:
				# TODO: error
				pass
			else:
				self.socket.write(line)
				self.fileSize = int(parts[1])
				print "File size", self.fileSize

		else:
			# It's probably an error.
			self.socket.write(line)
			self.serverSocket.close()
			self.fileSize = -1
			self.received = 0
